/* soft_timer.c/h  3.0 */

#include "soft_timer.h"
#include "stdio.h"
#include "main.h"
#include "gpio.h"
#include "ds18b20.h"
#include "usart.h"
#include <rtthread.h>
volatile uint32_t tickCnt = 0;
static softTimer timer[TIMER_NUM];

extern struct rt_messagequeue static_mq0;
void TIM0_CB(void *argv, uint16_t argc) {
    gpio_toggle(GPIOE, GPIO_PIN_6);
}
void TIM1_CB(void *argv, uint16_t argc) {
    usart1_cache.data[0] = 1;
    usart1_cache.data[1] = usart1_cache.cnt >> 8;
    usart1_cache.data[2] = usart1_cache.cnt & 0x00ff;
    rt_mq_send(&static_mq0, &usart1_cache.data[0], USART_CACHE_LEN);
    memset(&usart1_cache, 0x00, sizeof(usart_cache));
    usart1_cache.cnt = 3;
}
void TIM2_CB(void *argv, uint16_t argc) {

}
void TIM3_CB(void *argv, uint16_t argc) {

}
void TIM4_CB(void *argv, uint16_t argc) {

}
void TIM5_CB(void *argv, uint16_t argc) {

}
void TIM6_CB(void *argv, uint16_t argc) {

}
void TIM7_CB(void *argv, uint16_t argc) {

}
void TIM8_CB(void *argv, uint16_t argc) {

}
void TIM9_CB(void *argv, uint16_t argc) {

}
/***
 *
 *
 * ***/

void tickCnt_Update(void) {
    tickCnt++;
}

uint32_t tickCnt_Get(void) {
    return tickCnt;
}

void softTimer_Init(void) {
    uint16_t i;

    for (i = 0; i < TIMER_NUM; i++) {
        timer[i].state = SOFT_TIMER_STOPPED;
        timer[i].mode = MODE_ONE_SHOT;
        timer[i].match = 0;
        timer[i].period = 0;
        timer[i].cb = NULL;
        timer[i].argv = NULL;
        timer[i].argc = 0;
    }
}

uint8_t softTimer_GetState(uint16_t id) {
    return timer[id].state;
}

void softTimer_Start(uint16_t id, tmrMode mode, uint32_t delay, callback *cb,
                     void *argv, uint16_t argc) {
    assert_param(id < TIMER_NUM);
    assert_param(mode == MODE_ONE_SHOT || mode == MODE_PERIODIC);
    timer[id].start = tickCnt_Get();
    timer[id].match = timer[id].start + delay;
    if (timer[id].match < timer[id].start) {
        timer[id].turn = TURN_OK;
    } else {
        timer[id].turn = TURN_NO;
    }
    timer[id].period = delay;
    timer[id].state = SOFT_TIMER_RUNNING;
    timer[id].mode = mode;
    timer[id].cb = cb;
    timer[id].argv = argv;
    timer[id].argc = argc;
}

void softTimer_Stop(uint16_t id) {
    assert_param(id < TIMER_NUM);
    timer[id].state = SOFT_TIMER_STOPPED;
}

void softTimer_Update(void) {
    uint16_t i;
    for (i = 0; i < TIMER_NUM; i++) {
        switch (timer[i].state) {
        case SOFT_TIMER_STOPPED:
            break;
        case SOFT_TIMER_RUNNING:
            if (timer[i].turn == TURN_NO) {
                if (timer[i].match <= tickCnt_Get()) {
                    timer[i].state = SOFT_TIMER_TIMEOUT;
                    timer[i].cb(timer[i].argv, timer[i].argc);
                }

            } else {
                if ((timer[i].match <= tickCnt_Get())
                        && (tickCnt_Get() < timer[i].start)) {
                    timer[i].state = SOFT_TIMER_TIMEOUT;
                    timer[i].cb(timer[i].argv, timer[i].argc);
                }
            }
            break;
        case SOFT_TIMER_TIMEOUT:
            if (timer[i].mode == MODE_ONE_SHOT) {
                timer[i].state = SOFT_TIMER_STOPPED;
            } else {
                timer[i].start = tickCnt_Get();
                timer[i].match = timer[i].start + timer[i].period;
                if (timer[i].match < timer[i].start) {
                    timer[i].turn = TURN_OK;
                } else {
                    timer[i].turn = TURN_NO;
                }
                timer[i].state = SOFT_TIMER_RUNNING;
            }
            break;
        default:
            break;
        }
    }
}
